# coding:utf8
from PIL import Image, ImageChops
import copy
import json
import numpy
# im= Image.open(r"E:\My_Spiders\qyxy\catpcha\456.bmp")
# print im.mode                       #查看图像的模式
# y,cb,cr=im1.getpixel((10,10)) #提取点(10,10)位置的亮度、蓝色分量、红色分量的值。
# print y                                    #输出亮度值
# im.show()
import pytesseract


# 3色去噪
def clean_RGB(img):
    # img2 = img.convert('RGB')
    detail_img = img.load()

    for x in range(img.size[0]):
        for y in range(img.size[1]):
            if not detail_img[x, y] == (255, 255, 255):
                rep = 0
                if detail_img[limit_add(x, img.size[0]), y] == (255, 255, 255):
                    rep+=1
                if detail_img[x, limit_add(y, img.size[1])] == (255, 255, 255):
                    rep += 1
                if detail_img[limit_sub(x), y] == (255, 255, 255):
                    rep += 1
                if detail_img[x, limit_sub(y)] == (255, 255, 255):
                    rep += 1
                if detail_img[limit_add(x, img.size[0]), limit_add(y, img.size[1])] == (255, 255, 255):
                    rep += 1
                if detail_img[limit_sub(x), limit_sub(y)] == (255, 255, 255):
                    rep += 1
                if detail_img[limit_sub(x), limit_add(y, img.size[1])] == (255, 255, 255):
                    rep += 1
                if detail_img[limit_add(x, img.size[0]), limit_sub(y)] == (255, 255, 255):
                    rep += 1
                if rep > 7:
                    detail_img[x, y] = (255, 255, 255)
    return img


# 去除噪点
def clean(img):
    detail_img = img.load()

    for x in range(img.size[0]):
        for y in range(img.size[1]):
            if detail_img[x, y] == 0:
                rep = 0
                if detail_img[x, y] == detail_img[limit_add(x, img.size[0]), y]:
                    rep+=1
                if detail_img[x, y] == detail_img[x, limit_add(y, img.size[1])]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_sub(x), y]:
                    rep += 1
                if detail_img[x, y] == detail_img[x, limit_sub(y)]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_add(x, img.size[0]), limit_add(y, img.size[1])]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_sub(x), limit_sub(y)]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_sub(x), limit_add(y, img.size[1])]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_add(x, img.size[0]), limit_sub(y)]:
                    rep += 1
                if rep < 2:
                    detail_img[x, y] = 255
    return img


# gsxt专用去噪（删除相同rgb值得噪音）
def gsxt_clean(img):
    high_limit = 150 # 150
    low_limit = 90 # 70
    detail_img = img.load()
    for x in range(img.size[0]):
        for y in range(img.size[1]):
            if detail_img[x, y][0] == detail_img[x, y][1] and detail_img[x, y][1] == detail_img[x, y][2]:
                detail_img[x, y] = (255, 255, 255)
            else:
                if low_limit <= detail_img[x, y][0] <= high_limit and low_limit <= detail_img[x, y][1] <= high_limit and low_limit <= detail_img[x, y][2] <= high_limit:
                    detail_img[x, y] = (255, 255, 255)
    return img


# 填充不完整的字
def full(img):
    detail_img = img.load()

    for x in range(img.size[0]):
        for y in range(img.size[1]):
            if detail_img[x, y] == 255:
                rep = 0
                if detail_img[x, y] == detail_img[limit_add(x, img.size[0]), y]:
                    rep+=1
                if detail_img[x, y] == detail_img[x, limit_add(y, img.size[1])]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_sub(x), y]:
                    rep += 1
                if detail_img[x, y] == detail_img[x, limit_sub(y)]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_add(x, img.size[0]), limit_add(y, img.size[1])]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_sub(x), limit_sub(y)]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_sub(x), limit_add(y, img.size[1])]:
                    rep += 1
                if detail_img[x, y] == detail_img[limit_add(x, img.size[0]), limit_sub(y)]:
                    rep += 1
                if rep < 2:
                    detail_img[x, y] = 0
    return img


# 在图片尺寸的限制下加x（默认为1）
def limit_add(inputs, limit, prs=1):
    if inputs + prs >= limit - 1:
        return limit - 1
    else:
        return inputs + prs


# 在图片尺寸的限制下减x (默认为1)
def limit_sub(inputs, prs=1):
    if inputs == 0:
        return 0
    else:
        return inputs - prs


# 获得从左起第一个字的切割坐标X1，Y1，X2，Y2
def cut_coordinate(cur_img123):
    cur_img = copy.deepcopy(cur_img123)
    co1_x = 0
    co1_y = 0
    co2_x = 0
    co2_y = 0
    de_img = cur_img.load()
    for x in range(cur_img.size[0]):
        res = 0
        for y in range(cur_img.size[1]):
            if de_img[x, y] == 0:
                co1_x = x
                res = 1
                # print co1_x
                break
        if res == 1:
            break

    for x in range(co1_x + 1, cur_img.size[0]):
        res = 0
        for y in range(cur_img.size[1]):
            if de_img[x, y] == 0:
                res += 1
                # print lx1
                break
        if res == 0:
            co2_x = x
            # print co2_x
            break

    region1 = (co1_x, 0, co2_x, cur_img.size[1])

    cropImg = cur_img.crop(region1)
    # cropImg.show()
    de_img2 = cropImg.load()
    for y in range(cropImg.size[1]):
        res = 0
        for x in range(cropImg.size[0]):
            if de_img2[x, y] == 0:
                co1_y = y
                res = 1
                break
        if not res == 0:
            # print co1_y
            break

    # print type(cropImg.size[1])
    for y in range(cropImg.size[1] - 1, 0, -1):
        res = 0
        # print 'y',y
        for x in range(cropImg.size[0]):
            if de_img2[x, y] == 0:
                co2_y = y
                res = 1
                break
        if not res == 0:
            # print co2_y
            break
    co_set = (co1_x, co1_y, co2_x, co2_y+1)
    return co_set


# 切割
def cut_all(cur_img, image_list=[]):
    # print image_list
    # if image_list:
    #     image_list = []
    image_lis = copy.copy(image_list)
    # cur_img = copy.deepcopy(cur_imgs)
    co1_x = 0
    co1_y = 0
    co2_x = 0
    co2_y = 0
    de_img = cur_img.load()
    for x in range(cur_img.size[0]):
        res = 0
        for y in range(cur_img.size[1]):
            if de_img[x, y] == 0:
                co1_x = x
                res = 1
                # print co1_x
                break
        if res == 1:
            break

    for x in range(co1_x + 3, cur_img.size[0]):
        res = 0
        for y in range(cur_img.size[1]):
            if de_img[x, y] == 0:
                res += 1
                # print lx1
                # break
        if res == 0:
            co2_x = x
            # print co2_x
            break
    # if co1_x == co2_x - 1:
    #     return image_list
    region1 = (co1_x, 0, co2_x, cur_img.size[1])

    cropImg = cur_img.crop(region1)
    # cropImg.show()
    de_img2 = cropImg.load()
    for y in range(cropImg.size[1]):
        res = 0
        for x in range(cropImg.size[0]):
            if de_img2[x, y] == 0:
                co1_y = y
                res = 1
                break
        if not res == 0:
            # print co1_y
            break

    # print type(cropImg.size[1])
    for y in range(cropImg.size[1] - 1, 0, -1):
        res = 0
        # print 'y',y
        for x in range(cropImg.size[0]):
            if de_img2[x, y] == 0:
                co2_y = y
                res = 1
                break
        if not res == 0:
            # print co2_y
            break
    co_set = (co1_x, co1_y, co2_x, co2_y+1)
    # print co_set

    if co2_x - co1_x + co2_y -co1_y <=10:
        return image_lis

    else:
        image_lis.append(cur_img.crop(co_set))
        # image_list.append(cur_img.crop(co_set))
        next_set = (co2_x, 0, cur_img.size[0], cur_img.size[1])
        rest = cur_img.crop(next_set)
        return cut_all(rest, image_lis)
        # yield rest


# 读取图片
def process_imgs(img_fi, h_limit=255, l_limit=170):
    # img_path = r'C:\Users\Administrator\Desktop\yzm\download_chapcha\6.jpg'
    # img_fi = Image.open(img_path)
    # im1 = Image.open(r'C:\Users\Administrator\Desktop\yzm\02.gif')
    im1 = gsxt_clean(img_fi)

    # 转化为灰度
    img = im1.convert('L')
    # haha.show()

    # 灰度阈值
    h_limit = h_limit
    l_limit = l_limit
    # print img.size
    haha = img.load()

    # 根据灰度阈值进行2值化
    for x in range(img.size[0]):
        for y in range(img.size[1]):
            if l_limit <= haha[x, y] <= h_limit:
                haha[x, y] = 255
            else:
                haha[x, y] = 0
    # img.show()

    # # 去除噪点和填充不完整的点
    # # clean_ato = clean(full(img))
    clean_ato = full(clean(img))
    # # clean_ato = img
    # # clean_ato.show()
    # img_list = cut_all(clean_ato)
    # # print img_list
    # # print len(img_list)
    return img

# # 获得切割左边第一个的坐标
# clean_ato_co = cut_coordinate(clean_ato)
# print 'coo', clean_ato_co
#
# # 切割左边第一个
# asdasda = clean_ato.crop(clean_ato_co)
# asdasda.show()


def pic_to_arr_list(img, x_s, y_s):
    # de_im = Image.open(image_path)
    out = img.resize((x_s, y_s), Image.ANTIALIAS)
    img_list = []

    pro_im = out.convert('L')
    detail_img = pro_im.load()
    for x in range(pro_im.size[0]):
        for y in range(pro_im.size[1]):
            img_list.append(detail_img[x,y])
    return img_list

def cal_cos(path1, path2):
    img1 = Image.open(path1)
    img2 = Image.open(path2)
    size1 = img1.size
    size2 = img2.size

    x_max = lcm(size1[0], size2[0])*2
    y_max = (x_max*size1[1])/size1[0]
    lis1 = pic_to_arr_list(img1, x_max, y_max)
    lis2 = pic_to_arr_list(img2, x_max, y_max)
    x = numpy.array(lis1)
    y = numpy.array(lis2)
    lx = numpy.sqrt(x.dot(x))
    ly = numpy.sqrt(y.dot(y))
    cos = x.dot(y) / (lx*ly)
    return cos

# 最小公倍数
def lcm(x, y):
   #  获取最大的数
   if x > y:
       greater = x
   else:
       greater = y

   while(True):
       if((greater % x == 0) and (greater % y == 0)):
           lcms = greater
           break
       greater += 1
   return lcms


# 去除背景，留下其余部分的彩色图片
def hunhe(img1):
    # img1 = img1.convert('RGB')
    img_l = img1.load()
    img_bw = process_imgs(img1)
    img_bw_l =img_bw.load()
    for x in range(img1.size[0]):
        for y in range(img1.size[1]):
            if img_bw_l[x, y] == 255:
                img_l[x, y] = (255, 255, 255)
    return img1


# 计算平均数
def average(seq):
    return float(sum(seq)) / len(seq)


# 对比两个颜色元祖，看看其3个值是否相近
def compare_yuanzu(tuple1, tuple2, limit=75):
    blank_tuple = (255, 255, 255)
    if tuple1 == blank_tuple or tuple2 == blank_tuple:
        return 1
    for index in range(3):
        if abs(tuple1[index] - tuple2[index]) >= limit:
            return 0
    return 1

# 对比一个元组的各项是否在list中的元组全部各项的极大值极小值之间
# 判断字大小
def compare_list_tuple(curr_list, tuple, limit=28):
    a = tuple[0]
    b = tuple[1]
    amin = 1000000
    amax = 0
    bmin = 1000000
    bmax = 0
    for new_tu in curr_list:
        if new_tu[0] < amin:
            amin = new_tu[0]
        if new_tu[0] > amax:
            amax = new_tu[0]
        if new_tu[1] < bmin:
            bmin = new_tu[1]
        if new_tu[1] > bmax:
            bmax = new_tu[1]
    if a > amax:
        if a - amin > limit:
            return 0
    if a < amin:
        if amin - a > limit:
            return 0
    if b > bmax:
        if b - bmin > limit:
            return 0
    if b < bmin:
        if bmin - b > limit:
            return 0
    return 1


# 求颜色(长度为3的元祖 '(R,G,B)' )平均值的类
class Img_Colors():
    def __init__(self):
        self.R_avg = 255
        self.G_avg = 255
        self.B_avg = 255
        # 坐标list
        self.color_list = []
        self.R_list = []
        self.G_list = []
        self.B_list = []
        self.avg_img = (255, 255, 255)

    # 计算平均数
    @staticmethod
    def average(seq):
        return int(float(sum(seq)) / len(seq))

    # 添加一个颜色,并更新平均值
    def add_color(self, yuanzu):
        self.color_list.append(yuanzu)
        self.R_list.append(yuanzu[0])
        self.G_list.append(yuanzu[1])
        self.B_list.append(yuanzu[2])
        self.R_avg = self.average(self.R_list)
        self.G_avg = self.average(self.G_list)
        self.B_avg = self.average(self.B_list)
        self.avg_img = (self.R_avg, self.G_avg, self.B_avg)

    # 计算当前点的个数
    def img_lens(self):
        return len(self.color_list)


# 按颜色分类图片
class Img_queue():
    def __init__(self, img):
        # 不同颜色Img_Color对象的列表
        self.img_color_list = []
        # 图片
        self.img = img
        self.img_load = img.load()
        self.cut_list = []
        # 图片有色坐标列表
        self.img_coo_list = self.create_coo_list(self.img)
        self.img_coo_list_rest = self.create_coo_list(self.img)
        # print 'coo', self.img_coo_list_rest
        # self.img_coo_list_rest = self.create_coo_list(self.img)
        self.process_rest_list()


    # 生产有色坐标的列表
    @staticmethod
    def create_coo_list(img):
        blank_tuple = (255, 255, 255)
        coo_list = []
        img_load = img.load()
        for x in range(img.size[0]):
            for y in range(img.size[1]):
                if not img_load[x, y] == blank_tuple:
                    coo_list.append((x, y))
        return coo_list

    # 从坐标列表中pop一个，随后找到列表中与其相似的点，pop出来并且组成一个新的列表
    def add_color(self):
        img_color = Img_Colors()

        self.img_coo_list_rest = self.create_coo_list(self.img)
        new_coo = self.img_coo_list_rest.pop(0)
        img_color.add_color(self.img_load[new_coo[0], new_coo[1]])
        new_img_coo_list = [new_coo]

        list_exp = copy.copy(self.img_coo_list_rest)
        for coo_tuple in list_exp:
            if compare_yuanzu(self.img_load[coo_tuple[0], coo_tuple[1]], img_color.avg_img) and compare_list_tuple(new_img_coo_list, coo_tuple):
                # print img_color.avg_img
                # print '???',img_color.color_list
                self.img_coo_list_rest.remove(coo_tuple)
                img_color.add_color(self.img_load[coo_tuple[0], coo_tuple[1]])
                new_img_coo_list.append(coo_tuple)
        if img_color.img_lens() >= 25:
            # print self.img_coo_list_rest
            self.img_color_list.append(new_img_coo_list)
            return new_img_coo_list
        else:
            img_del = copy.copy(self.img)
            img_del_l = img_del.load()
            for coo in new_img_coo_list:
                img_del_l[coo[0], coo[1]] = (255, 255, 255)
            self.img = img_del
            return []

    # def process_rest_list(self):
    #     if self.img_coo_list_rest:
    #         self.add_color()
    #         return self.img_color_list
    #         # print self.img_coo_list_rest

    def process_rest_list(self):
        while self.img_coo_list_rest:
            img_coo_list = self.add_color()
            i = img_coo_list
            if i:
                # print img_coo_list
                new_img = self.img.convert('RGB')
                new_img_load = new_img.load()
                for x in range(new_img.size[0]):
                    for y in range(new_img.size[1]):
                        if (x, y) in i:
                            # new_img_load[x, y] = (0, 0, 0)
                            pass
                        else:
                            new_img_load[x, y] = (255, 255, 255)
                # new_img.show()
                hihihi = hunhe(new_img)
                # sasasa = hihihi.convert('RGB')
                # hihihi.show()
                cao = blend(hihihi, haha)
                # cao.show()
                self.img = clean_RGB(cao)
                self.cut_list.append(hihihi)
                # print asdasda[0, 0]

        return self.img_color_list



# 在图片2中将图片1删除(置白)
def blend(img1, img2):
    img1_l = img1.load()
    img2_l = img2.load()
    img1_size_x = img1.size[0]
    img1_size_y = img1.size[1]
    img2_size_x = img2.size[0]
    img2_size_y = img2.size[1]
    if not (img1_size_x == img2_size_x and img1_size_y == img2_size_y):
        print '两个图片不一样大，你是不是sb？'
        return 0
    for x in range(img1_size_x):
        for y in range(img1_size_y):
            if img1_l[x, y] == img2_l[x, y]:
                img2_l[x, y] = (255, 255, 255)
    return img2


# 按坐标将图片切割，主要用于切割外wei白圈
def cut_one(img):
    cur_img = copy.deepcopy(img)
    co1_x = 0
    co1_y = 0
    co2_x = 0
    co2_y = 0
    de_img = cur_img.load()
    for x in range(cur_img.size[0]):
        res = 0
        for y in range(cur_img.size[1]):
            if not de_img[x, y] == (255, 255, 255):
                co1_x = x
                res = 1
                # print co1_x
                break
        if res == 1:
            break

    for x in range(cur_img.size[0]-1, co1_x + 1, -1):
        res = 0
        for y in range(cur_img.size[1]):
            if not de_img[x, y] == (255, 255, 255):
                res += 1
                # print lx1
                break
        if res == 1:
            co2_x = x
            # print co2_x
            break

    region1 = (co1_x, 0, co2_x, cur_img.size[1])

    cropImg = cur_img.crop(region1)
    # cropImg.show()
    de_img2 = cropImg.load()
    for y in range(cropImg.size[1]):
        res = 0
        for x in range(cropImg.size[0]):
            if not de_img2[x, y] == (255, 255, 255):
                co1_y = y
                res = 1
                break
        if not res == 0:
            # print co1_y
            break

    # print type(cropImg.size[1])
    for y in range(cropImg.size[1] - 1, 0, -1):
        res = 0
        # print 'y',y
        for x in range(cropImg.size[0]):
            if not de_img2[x, y] == (255, 255, 255):
                co2_y = y
                res = 1
                break
        if not res == 0:
            # print co2_y
            break
    co_set = (co1_x, co1_y, co2_x+1, co2_y+1)

    return img.crop(co_set)


# 按颜色完全切割成若干个图片
def cut_all_by_color(img, storage_path, name):
    haha = img.convert('RGB')
    new_img_ob = Img_queue(haha).cut_list
    count = 0
    for pic_glass in new_img_ob:
        cut_pic = cut_one(pic_glass)
        # cut_pic.show()
        cut_pic.save(storage_path + name + '_' + str(count+1) + '.gif')
        count += 1


if __name__ == "__main__":
    hehe = Image.open(r'C:\Users\Administrator\Desktop\yzm\test_color2.gif')
    haha = hehe.convert('RGB')
    haha_l = haha.load()
    # haha.show()

    # for i in range(12, 29):
    #     for j in range(21, 38):
    #         if not haha_l[i, j] == (255, 255, 255):
    #             print i, ',', j, '=', haha_l[i, j]

    # 按颜色切割 初步完成
    # #####
    # cut_color = Img_queue(haha)
    # ########
    new_pic_glass_list = cut_all_by_color(haha, 'C:\\Users\\Administrator\\Desktop\\yzm\\cut\\', '01')
    # print new_pic_glass_list
    # im_lis = cut_color.process_rest_list()
    # print im_lis
    # # print 'asdasda', cut_color.img_coo_list
    # # print i
    # for i in im_lis:
    #     new_img = haha.convert('RGB')
    #     new_img_load = new_img.load()
    #     for x in range(new_img.size[0]):
    #         for y in range(new_img.size[1]):
    #             if (x, y) in i:
    #                 # new_img_load[x, y] = (0, 0, 0)
    #                 pass
    #             else:
    #                 new_img_load[x, y] = (255, 255, 255)
    #     # new_img.show()
    #     hihihi = hunhe(new_img)
    #     # sasasa = hihihi.convert('RGB')
    #     asdasda = hihihi.load()
    #     hihihi.show()
    #
    #     cao = blend(hihihi, haha)
    #     cao.show()
    #     print asdasda[0, 0]



    # # 切割 198张验证码
    # for i in range(189, 411):
    #     img_paths = r'C:\Users\Administrator\Desktop\yzm\download_chapcha\%s.jpg' % i
    #     print img_paths
    #     image_list = process_imgs(img_paths)
    #     for img_index, img in enumerate(image_list):
    #         img.save(r'C:\Users\Administrator\Desktop\yzm\yzm_patch\%s_%s.jpg' % (i, img_index))

    # lis1 = pic_to_arr_list(r'C:\Users\Administrator\Desktop\yzm\test_cos\1.jpg', 170, 160)
    # lis2 = pic_to_arr_list(r'C:\Users\Administrator\Desktop\yzm\test_cos\2.jpg', 170, 160)

    # 计算相似度
    # print cal_cos(r'C:\Users\Administrator\Desktop\yzm\test_cos\1.jpg', r'C:\Users\Administrator\Desktop\yzm\test_cos\2.jpg')

    # # 测试 hunhe 获得去背景版的彩色图片
    # img1 = Image.open(r'C:\Users\Administrator\Desktop\yzm\download_chapcha\14.gif')
    # img2 = hunhe(img1)
    #
    # img2.show()
    # img2.save(r'C:\Users\Administrator\Desktop\yzm\test_color2.gif')
    # img3 = process_imgs(img1)
    # img3.show()

    # # 测试 yuanzu
    # hehe = Image.open(r'C:\Users\Administrator\Desktop\yzm\test_color.gif')
    # haha = hehe.convert('RGB')
    # haha_l = haha.load()
    # print haha_l[0, 0]
    # print haha_l[14, 34]
    # print haha_l[32, 26]
    # print haha_l[61, 28]
    # print haha_l[92, 31]
    # print haha_l[120, 37]
    #
    # yuanzu_list1 = []
    # yuanzu_list2 = []
    # yuanzu_list3 = []
    # for i in range(12, 29):
    #     for j in range(21, 38):
    #         if not haha_l[i, j] == (255, 255, 255):
    #             print i, ',', j, '=', haha_l[i, j]
    #             yuanzu_list1.append(haha_l[i, j][0])
    #             yuanzu_list2.append(haha_l[i, j][1])
    #             yuanzu_list3.append(haha_l[i, j][2])
    # print int(average(yuanzu_list1)), max(yuanzu_list1), min(yuanzu_list1)
    # print int(average(yuanzu_list2)), max(yuanzu_list2), min(yuanzu_list2)
    # print int(average(yuanzu_list3)), max(yuanzu_list3), min(yuanzu_list3)
    # none_tuple = (255, 255, 255)
    # for x in range(haha.size[0]):
    #     for y in range(haha.size[1]):
    #         if not haha_l[x, y] == none_tuple:

    # 利用谷歌的库来识别验证码，测试效果很差
    # import os
    #
    # os.chdir(r'E:\python\Lib\site-packages\pytesseract')
    # # img = Image.open('test-european.jpg')
    # # img = Image.open(r'C:\Users\Administrator\Desktop\yzm\test_cos\5.jpg')
    # img = Image.open(r'C:\Users\Administrator\Desktop\yzm\test_color.gif')
    #
    # img.show()
    # from pytesseract import image_to_string
    #
    # print image_to_string(img)
